import json
from io import BytesIO


from django.http import HttpResponse,JsonResponse
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.conf import settings
from django.contrib.auth.hashers import make_password, check_password
# Create your views here.
from .models import *
from .serializer import UserSerializer
from .utils.captcha import generate_captcha
from .utils.qiniu import upload_file
from .utils.b64 import cookie_base64_encoded_required,bs64_encoded,bs64_decoded
from .utils.token import generate_token,verify_token
from public_utils.email_caprcha import send_email


@csrf_exempt
def RegisterView(request):
    '''
    注册视图函数
    :param request:
    :return:
    '''
    if request.method == 'POST':
        json_data = json.loads(request.body)
        # 获取用户提交的注册信息
        emeail = json_data['name']
        password = json_data['pwd']
        name = json_data['nickname']
        age = json_data['age']
        sex = json_data['sex']
        College = json_data['college']
        verif_code = json_data['verification'].lower()  # 验证码
        email_code = json_data['email_code']  # 邮箱验证码
        if email_code != request.session.get("email_caprcha",""):
            return JsonResponse({"data":"false","msg": "邮箱验证码错误"}, status=200)
        elif verif_code != request.session.get("captcha_code", ""):
            return JsonResponse({"data":"false","msg": "验证码错误"}, status=200)
        else:
            # 如果数据库中没有相同账号，则允许创建新用户
            if Users.objects.filter(emeail=emeail):
                return JsonResponse({"data":"false","msg":"注册失败，该邮箱已经被注册"}, status=200)
            else:
                # 对密码进行加密处理
                password = make_password(password)
                print(password)
                # 创建新用户对象并保存到数据库中
                user = Users(emeail=emeail, password=password,name=name,age=age,sex=sex,College=College)
                user.save()
                return JsonResponse({"data":"true","msg":"注册成功"}, status=200)

    if request.method == 'GET':
        '''
        获取邮箱验证码，随机生成6位数字验证码，并发送到对方邮箱，然后将验证码存入session中。
        用户邮箱通过前端返回的name属性接收。ps: 前端传递的name属性值是用户输入的邮箱
        '''
        try:
            email = request.GET.get('name')
            print(email)
            # 发送邮箱的utils
            code, now = send_email(email)
            request.session['email_caprcha'] = code
            request.session['send_time'] = now
            request.session.set_expiry(settings.EMAIL_AGE)  # 设置session过期时间
            resp = JsonResponse({"msg":"验证码已发送至您的邮箱"}, status=200)
            return resp
        except Exception as e:
            print(e)
            return JsonResponse({"msg":"邮箱出错"}, status=200)



@csrf_exempt
def LoginView(request):
    '''
    登录视图函数,登录后设置session，并返回用户信息
    :param request:
    :return:
    '''
    if request.method == 'POST':
        '''
        检查session中是否存在is_login字段，如果不存在则返回未登录的响应
        '''
        json_data = json.loads(request.body)
        # 获取用户提交的登录信息
        emeail = json_data['name']
        password = json_data['pwd']
        # 查询数据库中是否有该用户
        try:
            user = Users.objects.get(emeail=emeail)
        except Users.DoesNotExist:
            return JsonResponse({"msg":"用户名或密码错误"}, status=200)

        # 验证密码是否正确（密码需要解密处理）
        if check_password(password,user.password) == False:
            return JsonResponse({"msg":"账号或者密码错误"}, status=200)
        else:
            # 返回登陆成功的响应
            session = request.session
            session['is_login'] = True
            request.session.set_expiry(settings.SESSION_COOKIE_AGE)
            print(user.get_sex_display())
            user_info = UserSerializer(user)
            data_dict = user_info.data   # 将序列化后的用户信息转换为字典形式
            token = generate_token({'user':user.id})
            data_dict['token'] = token
            resp = JsonResponse(data_dict)
            resp.set_cookie('user_id', bs64_encoded(user.id), max_age=60 * 60 * 1)  # 设置cookie，有效期为1小时
            return resp  # 返回响应

# 验证码视图函数
def get_captcha(request):
    img, code = generate_captcha()  # 生成验证码
    request.session['captcha_code'] = code.lower()  # 将验证码保存到session中
    buf = BytesIO()  # 创建一个BytesIO对象，用于存储验证码图片
    img.save(buf, 'png')  # 将验证码图片保存到BytesIO对象中
    return HttpResponse(buf.getvalue(),content_type="image/png",status=200)  # 返回验证码图片的二进制数据
    # return JsonResponse({'data': buf.getvalue()}, status=200)

# 判断是否登录视图函数
def if_login_cookie(request):
    if request.COOKIES.get('user_id'):
        try:
            user = Users.objects.get(id=bs64_decoded(request.COOKIES.get('user_id')))  # bs64_decoded(request.COOKIES.get('user_id'))
        except KeyError:
            resp = JsonResponse({"data": False, "msg": "未登录"}, status=200)
            return resp
        data_dict = UserSerializer(user).data
        resp = JsonResponse(data_dict, status=200)  # 如果有cookie，返回用户信息
        return resp
    else:
        resp = JsonResponse({"data":False,"msg":"未登录"}, status=200)
    return resp


# 登出视图函数
@csrf_exempt
def logout(request):
    if request.method == 'POST':
        resp = JsonResponse({"data":True,"msg":"退出成功"}, status=200)
        try:
            resp.delete_cookie('user_id')  # 删除cookie
            del request.session['is_login']  # 删除session
        except KeyError:
            pass
        return resp

# 修改用户信息视图函数
@csrf_exempt
def change_user_info(request):
    if request.method == 'POST':
        try:
            user_id = bs64_decoded(request.COOKIES.get('user_id'))
            user = Users.objects.get(pk=user_id)
        except KeyError:
            return JsonResponse({"data":False,"msg":"登录过期，请重新登录"}, status=200)
        json_data = json.loads(request.body)
        user.password = json_data['pwd'] if json_data['pwd'] else user.password
        user.name = json_data['nickname'] if json_data['nickname'] else user.name
        user.age = json_data['age'] if json_data['age'] else user.age
        user.sex = json_data['sex'] if json_data['sex'] else user.sex
        user.College = json_data['college'] if json_data['college'] else user.College
        user.save()
        # 返回修改成功的响应，还是返回用户修改后的新数据
        return JsonResponse({"data":True,"msg":"修改成功"}, status=200)

# 上传头像视图函数
@csrf_exempt
def upload_img(request):
    if request.method == 'POST':
        try:
            user_id = bs64_decoded(request.COOKIES.get('user_id'))
            user = Users.objects.get(pk=user_id)
        except KeyError:
            return JsonResponse({"data":False,"msg":"登录过期，请重新登录"}, status=200)
        # json_data = json.loads(request.body)
        user_img = request.FILES['file'].file  # 获取用户上传的头像图片文件流
        file_name = upload_file(settings.AK, settings.SK, user_img)
        user.img = f'{settings.BUCKET_URL}/{file_name}'
        user.save()  # 将头像地址保存到数据库中
        print(f'文件地址:{settings.BUCKET_URL}/{file_name}')
        return JsonResponse({'data':'调用了接口',"user_img":user.img},status=200)


@method_decorator(csrf_exempt, name='dispatch')
class Reset_pwd(View):
    def get(self, request):
        # 获取用户传递过来的email
        emeail = request.GET.get("emeail")
        # 通过email查询数据库，如果存在，则发送验证码，并设置token值，否则返回错误信息
        try:
            user = Users.objects.filter(emeail=emeail)
        except IndexError:
            return JsonResponse({"data": False, "msg": "该邮箱没有注册"}, status=200)
        else:
            code, now = send_email(emeail)  # 发送验证码
            # 通过邮箱设置token值
            token = generate_token({'email':emeail})
            # 将验证码储存到session中设置有效期为settings.EMAIL_AGE
            request.session['reset_pwd_code'] = code
            request.session.set_expiry(settings.EMAIL_AGE)
            resp = JsonResponse({"data": True, "msg": "验证码已发送至您的邮箱",'token':token}, status=200)
            return resp

    def put(self, request):
        # 获取用户传递过来的email和密码，包括token，token的有效期为settings.TOOKEN_EXPIRE
        data = json.load(request)
        emeail = data["emeail"]
        pwd = data["pwd"]
        code = data["code"]
        token = data["token"]
        if code == request.session.get('reset_pwd_code', ''):
            try:  # 尝试解密验证token
                payload = verify_token(token)
            except Exception:
                return JsonResponse({"data": False, "msg": "验证码已经失效"}, status=200)
            else:  # 如果解密成功，则修改密码，并保存到数据库中
                user = Users.objects.get(emeail=emeail)  # 获取用户对象
                pwd = make_password(pwd) # 加密密码
                user.password = pwd  # 修改密码
                user.save()  # 保存到数据库
            return JsonResponse({"data": True, "msg": "重置密码成功"}, status=200)
        else:
            return JsonResponse({"data": False, "msg": "验证码错误"}, status=200)


